package com.xujie.chat.client;

import com.xujie.chat.client.handler.ClientInit;
import com.xujie.chat.message.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.xujie.chat.message.NettyConstant.CLIENT_ID_KEY;

/**
 * @author Xujie
 * @since 2024/12/28 23:53
 **/


public class MyClient implements Runnable {
	private Logger log = LoggerFactory.getLogger(MyClient.class);
	private Channel channel;
	private boolean isUserColse = false;
	private ExecutorService executorService = Executors.newFixedThreadPool(10);
	EventLoopGroup workerGroup = new NioEventLoopGroup();

	@Override
	public void run() {
		try {
			connect();
		} catch (InterruptedException e) {
			e.printStackTrace();
			log.error("连接服务器失败");
		}
	}

	private void connect() throws InterruptedException {
		Bootstrap bootstrap = new Bootstrap();
		bootstrap.group(workerGroup)
						.channel(NioSocketChannel.class)
						.handler(new ClientInit());

		try {
			synchronized (this) {
				ChannelFuture connect = bootstrap.connect(new InetSocketAddress(NettyConstant.SERVER_IP, NettyConstant.SERVER_PORT)).sync();
				log.info("连接服务器成功");
				channel = connect.channel();
				connect.channel().closeFuture().sync();
			}
		} finally {
			if (!isUserColse) {
				log.error("连接断开，开始重连");
				executorService.execute(() -> {
					try {
						Thread.sleep(1000);
						connect();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				});
			}
		}
	}

	public void sendMsg(String msg) {
		if (channel == null || !channel.isActive()) {
			throw new IllegalStateException("和服务器还未未建立起有效连接！" +
							"请稍后再试！！");
		}
		channel.writeAndFlush(buildMsg(msg));
	}

	private MyMessage buildMsg(String message) {
		MyMessage msg = new MyMessage();
		MsgHeader msgHeader = new MsgHeader();
		msgHeader.setMsgID(MakeMsgID.getID());
		msgHeader.setType(MessageType.MESSAGE.value());
		msgHeader.setClientId(channel.attr(CLIENT_ID_KEY).get());
		msgHeader.setMd5(EncryptUtils.encryptObj(message));
		msg.setMyHeader(msgHeader);
		msg.setBody(message);
		return msg;
	}

	public void close() {
		isUserColse = true;
		workerGroup.shutdownGracefully();
	}

	public void showOnlineClients() {
		if (channel == null || !channel.isActive()) {
			throw new IllegalStateException("和服务器还未未建立起有效连接！" +
							"请稍后再试！！");
		}
		MyMessage msg = new MyMessage();
		MsgHeader msgHeader = new MsgHeader();
		msgHeader.setMsgID(MakeMsgID.getID());
		msgHeader.setType(MessageType.SHOW_ONLINE_CLIENT.value());
		msgHeader.setClientId(channel.id().asLongText());
		msg.setMyHeader(msgHeader);
		channel.writeAndFlush(msg);
	}

	public void sendMsgToClient(String clientId, String msg) {
		if (channel == null || !channel.isActive()) {
			throw new IllegalStateException("和服务器还未未建立起有效连接！" +
							"请稍后再试！！");
		}
		MyMessage message = new MyMessage();
		MsgHeader msgHeader = new MsgHeader();
		msgHeader.setMsgID(MakeMsgID.getID());
		msgHeader.setMd5(EncryptUtils.encrypt(clientId + msg));
		msgHeader.setType(MessageType.MESSAGE.value());
		msgHeader.setClientId(channel.id().asLongText());
		msgHeader.setToClientId(clientId);
		message.setMyHeader(msgHeader);
		message.setBody(msg);
		channel.writeAndFlush(message);
	}

	public void showMyClientId() {
		if (channel == null || !channel.isActive()) {
			throw new IllegalStateException("和服务器还未未建立起有效连接！" +
							"请稍后再试！！");
		}
		System.out.println("我的客户端ID：" + channel.attr(NettyConstant.CHANNEL_ID_KEY).get());
	}
}
